package com.cmwa.solution.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.cmwa.ec.base.util.SpringUtil;
import com.cmwa.solution.exception.FileUploadException;
import com.cmwa.solution.sys.attach.entity.AttachVo;

public class FileUtil {

	/**
	 * 保存单个文件到服务器
	 * 
	 * @param request
	 * @param inputFileName
	 *            表单file控件name
	 * @param MAX_FILE_SIZE
	 *            上传文件允许最大值
	 * @return
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static Map<String, String> saveSingleFileToServer(HttpServletRequest request, String inputFileName, long MAX_FILE_SIZE) throws IOException, FileNotFoundException {
		String isOK = Constant.FILE_UPLOAD_SUCCESS;
		String errorMessage = null;
		String fileName = null;
		String filePath = null;

		Map<String, String> resultMap = new HashMap<String, String>();
		// 获取附件的默认文件夹路径,不存在就创建文件夹
		String fileDirPath = createFullFileDir();
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

		// 检查文件大小，以减轻对服务器内存的压力
		int contextLength = request.getContentLength();
		if (contextLength > (Constant.MAX_ECTRINIC_CONTRACT_FILE_SIZE + 460)) {
			isOK = Constant.FILE_UPLOAD_ERROR;
			errorMessage = "错误：上传的文件超出大小限制！请上传附件大小为200M以下的文件";
		} else {
			MultipartFile mFile = multipartRequest.getFile(inputFileName);

			if (mFile != null && !mFile.isEmpty()) {
				noExistsAndMake(fileDirPath);
				fileName = mFile.getOriginalFilename();
				filePath = fileDirPath + File.separator + createFullFileName(fileName);
				mFile.transferTo(new File(filePath));
			} else {
				isOK = Constant.FILE_UPLOAD_ERROR;
				errorMessage = "错误：上传的文件不存在！";
			}
		}
		resultMap.put("isOK", isOK);
		resultMap.put("fileName", fileName);
		resultMap.put("filePath", filePath);
		resultMap.put("errorMessage", errorMessage);
		return resultMap;
	}

	/**
	 * 保存上传request中的单个文件到服务器
	 * 
	 * @param request
	 * @param inputFileName
	 * @return
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static AttachVo saveSingleFileToServer(HttpServletRequest request, String inputFileName) throws FileUploadException {
		// 获取附件的默认文件夹路径,不存在就创建文件夹
		String fileDirPath = createFullFileDir();
		return uploadFileToService(request, inputFileName,fileDirPath);
	}
	
	/**
	 * 保存上传request中的单个文件到服务器
	 * 
	 * @param request
	 * @param inputFileName
	 * @return
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static AttachVo saveContractToServer(HttpServletRequest request, String inputFileName) throws FileUploadException {
		// 获取附件的默认文件夹路径,不存在就创建文件夹
		String fileDirPath = SpringUtil.getProperty("sys.tmpFileBasePath") + File.separator + "solution" + File.separator + "offline_tmplt";
		return uploadFileToService(request, inputFileName,fileDirPath);
	}

	private static AttachVo uploadFileToService(HttpServletRequest request,
			String inputFileName,String fileDirPath) throws FileUploadException {
		String isOK = Constant.FILE_UPLOAD_SUCCESS;
		String errorMessage = null;
		String fileName = null;
		String filePath = null;

		AttachVo attach = new AttachVo();
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

		// 检查文件大小，以减轻对服务器内存的压力
		int contextLength = request.getContentLength();
		String sizeLimit = request.getParameter("fileSizeLimit");
		String limitMsg = request.getParameter("fileSizeLimitMsg");
		Long sizeLimitLong;
		if(StringUtils.isNotEmpty(sizeLimit)){
			sizeLimitLong = Long.parseLong(sizeLimit) + 460;
		}else{
			sizeLimitLong = (Constant.MAX_UPLOAD_FILE_SIZE + 460);
		}
		if (contextLength > sizeLimitLong) {
			isOK = Constant.FILE_UPLOAD_ERROR;
			errorMessage = StringUtils.isNotEmpty(limitMsg) ? limitMsg :"错误：上传的文件超出大小限制！请上传附件大小为30M以下的文件";
		} else {
			try {
				// 取得一个inputFileName中的MultipartFile，保存到服务器上固定的目录中
				MultipartFile mFile = multipartRequest.getFile(inputFileName);
				if (mFile != null && !mFile.isEmpty()) {
					noExistsAndMake(fileDirPath);
					fileName = mFile.getOriginalFilename();
					filePath = fileDirPath + File.separator + createFullFileName(fileName);
					mFile.transferTo(new File(filePath));
				} else {
					isOK = Constant.FILE_UPLOAD_ERROR;
					errorMessage = "错误：上传的文件不存在或为空文件！";
				}
			} catch (IllegalStateException e) {
				// 出异常，则本次上传无效，删除文件
				if (filePath != null)
					deleteFile(new File(filePath));
				throw new FileUploadException(e.getCause());
			} catch (IOException e) {
				if (filePath != null)
					deleteFile(new File(filePath));
				throw new FileUploadException(e.getCause());
			}
		}
		attach.setAttName(fileName);
		attach.setAttPath(filePath);
		attach.setIsOK(isOK);
		attach.setErrorMessage(errorMessage);
		return attach;
	}

	/**
	 * 保存上传request中的多个文件到服务器
	 * 
	 * @param request
	 * @param inputFileName
	 * @return
	 * @throws FileUploadException
	 */
	public static List<AttachVo> saveMultiFileToServer(HttpServletRequest request, String inputFileName) throws FileUploadException {
		String	isOK = Constant.FILE_UPLOAD_ERROR;
		String errorMessage = null;
		String fileName = null;
		String filePath = null;

		List<AttachVo> resultList = new ArrayList<AttachVo>();
		// 获取附件的默认文件夹路径,不存在就创建文件夹
		String fileDirPath = createFullFileDir();
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

		// 检查文件大小，以减轻对服务器内存的压力
		int contextLength = request.getContentLength();
		if (contextLength > (Constant.MAX_UPLOAD_FILE_SIZE + 460)) {
			errorMessage = "错误：上传的文件超出大小限制！请上传附件大小为30M以下的文件";
			AttachVo attach = new AttachVo();
			attach.setIsOK(isOK);
			attach.setErrorMessage(errorMessage);
			resultList.add(attach);
		} else {
			// 取得同一个inputFileName中的所有MultipartFile，遍历并保存到服务器上固定的目录中
			List<MultipartFile> mFiles = multipartRequest.getFiles(inputFileName);
			for (int i = 0; mFiles != null && i < mFiles.size(); i++) {
				try {
					MultipartFile mFile = mFiles.get(i);
					//初始化默认值
					fileName = null;
					filePath = null;
					isOK = Constant.FILE_UPLOAD_ERROR;
					errorMessage = "错误：上传的文件不存在！";
					//立即记录入列表，以免文件保存入硬盘过程中出异常时没有被记录
					AttachVo attach = new AttachVo();
					attach.setIsOK(isOK);
					attach.setErrorMessage(errorMessage);
					resultList.add(attach);
					//文件保存到硬盘
					if (mFile != null && !mFile.isEmpty()) {
						noExistsAndMake(fileDirPath);
						fileName = mFile.getOriginalFilename();
						filePath = fileDirPath + File.separator + createFullFileName(fileName);
						mFile.transferTo(new File(filePath));
						isOK = Constant.FILE_UPLOAD_SUCCESS;
						errorMessage="上传成功！";
					}
					//更新附件一些属性状态信息
					attach.setAttName(fileName);
					attach.setAttPath(filePath);
					attach.setIsOK(isOK);
					attach.setErrorMessage(errorMessage);
				} catch (IllegalStateException e) {
					e.getCause();
				} catch (IOException e) {
					e.getCause();
				}
			}
		}
		return resultList;
	}


	/**
	 * 删除单个无效的附件文件
	 * 
	 * @param attachVo
	 */
	public static void deleteInvalidAttachFile(AttachVo attachVo) {
		// 标志为错误
		attachVo.setIsOK(Constant.FILE_UPLOAD_ERROR);
		// 设置错误信息
		attachVo.setErrorMessage("文件无效");
		// 删除硬盘上存在的无效的文件
		if (StringUtils.isNotBlank(attachVo.getAttPath())) {
			File file = new File(attachVo.getAttPath());
			deleteFile(file);
		}
	}

	/**
	 * 文件目录不存在则创建
	 * 
	 * @param fileDirPath
	 */
	public static void noExistsAndMake(String fileDirPath) {
		File tempDir = new File(fileDirPath);
		if (!tempDir.exists()) {// 创建目录
			tempDir.mkdirs();
		}
	}

	/**
	 * 取得文件的后缀名
	 * 
	 * @param fileName
	 * @return
	 */
	public static String getExtend(String fileName) {
		if (fileName.lastIndexOf(".") != -1) {
			return fileName.substring(fileName.lastIndexOf("."));
		}
		return null;
	}

	/**
	 * 生成UUID字符串
	 * 
	 * @return
	 */
	private static String getUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 创建一个文件保存的路径，基于系统配置文件的目录位置
	 * 
	 * @return
	 */
	public static String createFullFileDir() {
		String dateTimeDir = DateUtils.getNowStr(DateUtils.DATE_FORMAT_yMdHms_EN1);
		String fullFilePath = SpringUtil.getProperty("sys.tmpFileBasePath") + File.separator + dateTimeDir.substring(0, 4) + File.separator + dateTimeDir.substring(0, 8);
		return fullFilePath;
	}

	/**
	 * 生成 一个流水的文件名称
	 * 
	 * @param originalFilename
	 * @return
	 */
	public static String createFullFileName(String originalFilename) {
		String dateTimeDir = DateUtils.getNowStr(DateUtils.DATE_FORMAT_yMdHms_EN1);
		String fullFileName = dateTimeDir + getUUID() + getExtend(originalFilename);
		return fullFileName;
	}

	/**
	 * 创建一个完整的路径名，包括文件路径和文件名称
	 * 
	 * @param make
	 *            不存在文件夹，则创建
	 * @param originalFilename
	 * @return
	 */
	public static String createFullFilePath(String originalFilename, boolean make) {
		if (make) {
			noExistsAndMake(createFullFileDir());
		}
		return createFullFileDir() + File.separator + FileUtil.createFullFileName(originalFilename);
	}

	/**
	 * 获取不包含后缀的文件名
	 * 
	 * @param fileName
	 * @return
	 */
	public static String getFileNameExceptExt(String fileName) {
		if (fileName.lastIndexOf(".") != -1) {
			return fileName.substring(0, fileName.lastIndexOf("."));
		}
		return fileName;
	}

	/**
	 * 如果文件存在，则删除文件
	 * 
	 * @param file
	 * @return
	 */
	public static boolean deleteFile(File file) {
		if (!file.exists())
			return false;
		return file.delete();
	}
	
	/**
	 * 删除文件夹下的所有文件
	 * 
	 * @param oldFile
	 */
	public static void deleteFileDir(File oldFile) {
		if (oldFile.isDirectory()) {
			File[] files = oldFile.listFiles();
			for (File file : files) {
				if (file.isDirectory()) {
					deleteFileDir(file);
				} 
				deleteFile(file);
			}
		} else {
			deleteFile(oldFile);
		}
	}
	
	/**
	 * 根据文件路径，获取文件大小
	 * 
	 * @return
	 * @throws IOException
	 */
	public static int getFileSize(String filePath) throws IOException {
		File file = new File(filePath);
		if (file.isFile()) {
			InputStream fis = new FileInputStream(file);
			byte[] data = readStream(fis);
			fis.close();
			return data.length;
		}
		return 0;
	}

	/**
	 * 输入流转字节数组
	 * 
	 * @param inStream
	 * @return
	 * @throws IOException
	 */
	public static byte[] readStream(InputStream inStream) throws IOException {
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inStream.read(buffer)) != -1) {
			outSteam.write(buffer, 0, len);
		}
		outSteam.close();
		inStream.close();
		return outSteam.toByteArray();
	}
	
	
}
